<!--
 * @Author: doing
 * @Date: 2023-08-10 10:21:19
 * @LastEditors: git config user.name && git config user.email
 * @LastEditTime: 2023-09-02 21:23:18
 * @FilePath: \background-management-system\src\pages\user\index.vue
 * @Description: 
 * 用户管理页面
 * Copyright (c) 2023 by 1540265624@qq.com, All Rights Reserved. 
-->
<template>
    <div>
        <!-- 卡片视图区域 -->
        <el-card v-loading="isUserListLoading">
            <!-- 实现表单模块 -->
            <el-form ref="searchRef" :model="searchForm" class="flex">
                    <el-form-item label="用户名" class="mr-4" prop="username">
                        <el-input style="width: 150px;" placeholder="请输入用户名" v-model="searchForm.username"></el-input>
                    </el-form-item>
                    <el-form-item label="手机号" class="mr-4" prop="mobile">
                        <el-input style="width: 150px;" placeholder="请输入手机号" v-model="searchForm.mobile"></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="findUser" v-permission="['user:search']">
                            <el-icon style="vertical-align: middle;">
                                <search />
                            </el-icon>
                            <span style="vertical-align: middle;">查询</span>
                        </el-button>
                        <el-button @click="resetUserList">
                            <el-icon style="vertical-align: middle;">
                                <RefreshLeft />
                            </el-icon>
                            <span style="vertical-align: middle;">重置</span>
                        </el-button>
                        <el-button type="primary" @click="handleAdd"  v-permission="['user:add']">
                            <el-icon style="vertical-align: middle;">
                                <CirclePlus />
                            </el-icon>
                            <span style="vertical-align: middle;">新增</span>
                        </el-button>
                    </el-form-item>
            </el-form>

            <!-- 实现表格和分页 -->
                <el-table :data="userList" border :table-layout="tableLayout" :cell-style="{ textAlign: 'center' }" :header-cell-style="{textAlign: 'center'}">
                    <el-table-column type="index" label="序号" porp="id"></el-table-column>
                    <el-table-column label="用户名" prop="username"></el-table-column>
                    <el-table-column label="昵称" prop="nickName"></el-table-column>
                    <el-table-column label="头像" prop="imageUrl" min-width="130px">
                        <template #default="{ row }">
                            <el-image style="width: 100px; height: 100px" :src="row.imageUrl" :fit="fit">
                                <template #error>
                                    <div class="image-slot">
                                        <el-icon>
                                            <PictureFilled />
                                        </el-icon>
                                    </div>
                                </template>
                            </el-image>
                        </template>
                    </el-table-column>
                    <el-table-column label="手机号" prop="mobile"></el-table-column>
                    <el-table-column label="邮箱" prop="email"></el-table-column>
                    <el-table-column label="账号过期" prop="isAccountNonExpired">
                        <template v-slot="scope">
                            <el-tag type="success" v-if="scope.row.isAccountNonExpired">正常</el-tag>
                            <el-tag type="warning" v-else>不正常</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="账号锁定" prop="isAccountNonLocked">
                        <template v-slot="scope">
                            <el-tag type="success" v-if="scope.row.isAccountNonLocked">正常</el-tag>
                            <el-tag type="warning" v-else>不正常</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="密码过期" prop="isCredentialsNonExpired">
                        <template v-slot="scope">
                            <el-tag type="success" v-if="scope.row.isCredentialsNonExpired">正常</el-tag>
                            <el-tag type="warning" v-else>不正常</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="是否可用" prop="isEnabled">
                        <template v-slot="scope">
                            <el-tag type="success" v-if="scope.row.isEnabled">可用</el-tag>
                            <el-tag type="warning" v-else>不可用</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="更新时间" prop="updateDate">
                        <template  #default="{ row }">
                            {{ formatTime(row.updateDate) }}
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" width="auto" min-width="280px">
                        <template v-slot="scope">
                            <el-row :gutter="20" class="flex justify-center">
                                <el-tooltip content="编辑" placement="top" class="btn">
                                    <el-button type="success" @click="handleEdit(scope.row)" icon="Edit" v-permission="['user:edit']" />
                                </el-tooltip>
                                <el-tooltip content="删除" placement="top" class="btn">
                                    <el-button type="danger" @click="handleDelete(scope.row.id)" icon="Delete" v-permission="['user:delete']" />
                                </el-tooltip>
                                <el-tooltip content="分配角色" placement="top" class="btn">
                                    <el-button type="primary" icon="User" @click="assignRole(scope.row.id)" v-permission="['user:role']" />
                                </el-tooltip>
                                <el-tooltip content="密码修改" placement="top" class="btn" >
                                    <el-button type="primary" icon="Lock" @click="chgePwd(scope.row.id)" v-permission="['user:password']"/>
                                </el-tooltip>
                            </el-row>
                        </template>
                    </el-table-column>
                </el-table>

            <el-pagination v-model:current-page="page.current" v-model:page-size="page.size"
                :page-sizes="[20, 50, 100]" :disabled="disabled" :background="background"
                layout="total, sizes, prev, pager, next, jumper" :total="page.total" @size-change="handleSizeChange"
                @current-change="handleCurrentChange" />

        </el-card>

        <!-- 抽屉组件 -->
        <form-drawer ref="formDrawerRef" :title="drawerTitile" :destroyOnClose="true" @submit="drawerSubmit" @clean="cleanForm">
            <el-form ref="formRef" :rules="rules" :model="form" label-width="80px" size="small">
                <el-form-item prop="imageUrl">
                    <!-- 上传图片 -->
                    <el-upload class="avatar-uploader" accept="image/*" :show-file-list="false"
                        :http-request="uploadMainImg">
                        <img v-if="form.imageUrl" :src="form.imageUrl" class="avatar">
                        <i v-else class="avatar-uploader-icon">
                            <el-icon>
                                <Plus />
                            </el-icon>
                        </i>
                    </el-upload>
                </el-form-item>
                <el-form-item prop="nickName" label="昵称">
                    <el-input v-model="form.nickName" placeholder="昵称不能为空"></el-input>
                </el-form-item>
                <el-form-item prop="username" label="用户名">
                    <el-input v-model="form.username" placeholder="用户名不能为空"></el-input>
                </el-form-item>
                <el-form-item prop="password" label="密码" v-if="isAddOrEdit">
                    <el-input v-model="form.password" placeholder="密码不能为空"></el-input>
                </el-form-item>
                <el-form-item prop="mobile" label="电话号码">
                    <el-input v-model="form.mobile" placeholder="电话号码不能为空"></el-input>
                </el-form-item>
                <el-form-item prop="email" label="邮箱">
                    <el-input v-model="form.email" placeholder="邮箱不能为空"></el-input>
                </el-form-item>
                <el-form-item prop="isAccountNonExpired" label="账号过期">
                    <el-radio-group v-model="form.isAccountNonExpired">
                        <el-radio :label="1" size="large" border>正常</el-radio>
                        <el-radio :label="0" size="large" border>不正常</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item prop="isAccountNonLocked" label="账号锁定">
                    <el-radio-group v-model="form.isAccountNonLocked">
                        <el-radio :label="1" size="large" border>正常</el-radio>
                        <el-radio :label="0" size="large" border>不正常</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item prop="isCredentialsNonExpired" label="密码过期">
                    <el-radio-group v-model="form.isCredentialsNonExpired">
                        <el-radio :label="1" size="large" border>正常</el-radio>
                        <el-radio :label="0" size="large" border>不正常</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item prop="isEnabled" label="是否可用">
                    <el-radio-group v-model="form.isEnabled">
                        <el-radio :label="1" size="large" border>可用</el-radio>
                        <el-radio :label="0" size="large" border>不可用</el-radio>
                    </el-radio-group>
                </el-form-item>
            </el-form>
        </form-drawer>

        
        <!-- 分配角色组件 -->
        <assign-roles ref="assignRef" :title="assignTitle" destroyOnClose @clean="cleanRoleForm">
            <el-form class="roleList-scrollbar" ref="assignFormRef" :model="assignSearchForm">
                <el-form-item label="角色名称" prop="name">
                    <el-input style="width: 150px;" v-model="assignSearchForm.name"></el-input>
                    <el-button type="primary" @click="findRole" class="ml-4">
                        <el-icon style="vertical-align: middle;">
                            <search />
                        </el-icon>
                        <span style="vertical-align: middle;">查询</span>
                    </el-button>
                    <el-button @click="resetRoleForm" class="ml-2">
                        <el-icon style="vertical-align: middle;">
                            <RefreshLeft />
                        </el-icon>
                        <span style="vertical-align: middle;">重置</span>
                    </el-button>
                    <el-button type="success" @click="assignRolesSubmit" class="ml-2">
                        <el-icon style="vertical-align: middle;">
                            <CirclePlus />
                        </el-icon>
                        <span style="vertical-align: middle;">设置角色</span>
                    </el-button>
                </el-form-item>
            </el-form>
            <el-scrollbar max-height="160px" class="roleList-scrollbar">
                <el-table ref="assignTableRef" :data="assignTable" @select-all="selectAll" v-loading="isRoleListLoading"
                    border>
                    <el-table-column size="small" type="selection" align="center">
                        <template #default="scope">
                            <el-checkbox v-model="scope.row.checked" @change="select" />
                        </template>
                    </el-table-column>
                    <el-table-column property="id" label="id" width="120" />
                    <el-table-column property="name" label="角色名称" />
                    <el-table-column property="remark" label="备注" />
                </el-table>
            </el-scrollbar>
            <el-pagination v-model:current-page="rolePage.current" v-model:page-size="rolePage.size"
                :page-sizes="[20, 50, 100]" :disabled="disabled" :background="background"
                layout="total, sizes, prev, pager, next, jumper" :total="rolePage.total" @size-change="roleHandleSizeChange"
                @current-change="roleHandleCurrentChange" />
        </assign-roles>

        <!-- 修改密码组件 -->
        <form-dialog ref="chgePwdRef" :title="chgePwdTitle" destroyOnClose @submit="chgePwdSubmit"
            @clean="cleanPwdForm">
            <el-form ref="chgePwdFormRef" :rules="chgePwdRules" :model="chgePwdform" label-width="80px" size="small">
                <el-form-item label="旧密码" prop="oldPassword">
                    <el-input placeholder="请输入旧密码" v-model="chgePwdform.oldPassword"></el-input>
                </el-form-item>
                <el-form-item label="新密码" prop="newPassword">
                    <el-input placeholder="请输入新密码" v-model="chgePwdform.newPassword" show-password></el-input>
                </el-form-item>
            </el-form>
        </form-dialog>
    </div>
</template>
<script setup>
import { computed, ref, reactive, nextTick, onMounted } from 'vue'
import FormDrawer from '~/components/FormDrawer.vue'
import FormDialog from '~/components/FormDialog.vue'
import AssignRoles from '~/pages/user/components/AssignRoles.vue'
import {
    emailValidator,
    telValidator
} from '~/composables/rule.js'
import {
    showModal,
    toast,
    formatTime
} from '~/composables/util.js'
import {
    searchUser,
    updataUser,
    deleteUser,
    addUser,
    getUserRoleId,
    getUserTotal,
    searchRole,
    updataUserRole,
    validateOldPassword,
    updataPassword,
    uploadPic,
    deletePic
} from '~/api/user.js'
//初始化数据开始
const fit = ref('contain')
const tableLayout = ref('fixed')
const isAddOrEdit = ref(true)
const isUserListLoading = ref(false)
const drawerTitile = computed(() => isAddOrEdit.value ? '新增' : '修改')
const userList = ref([])
const page = reactive({
    current: 1,
    size: 20,
    total: 0
})
const searchRef = ref(null)
const searchForm = reactive({})
const Init = async function () {
    isUserListLoading.value = true

    const body = {...page,...searchForm}
    console.log('传递的参数是')
    console.log(body)

    //获取用户信息列表
    await searchUser(body).then(res=>{
        console.log(res)
        userList.value = res.data.data.records
    })
    //获取总用户总数
    await getUserTotal().then(res=>{
        page.total = res.data.data
    })
    isUserListLoading.value = false
}


onMounted(async () => {
    Init()
})




//初始化数据结束

//分页内容开始(待开发)
const disabled = ref(false)
const background = ref(true)

const handleSizeChange = async function () {
    Init()
}
const handleCurrentChange = async function () {
    Init()  
}
//分页内容结束

//操作栏开始
//删除操作
const handleDelete = function (id) {
    showModal('是否要删除该数据?').then(async () => {
        toast('正在删除中...', 'info', false, 3000)
        await deleteUser(id).then(res => {
            toast('删除成功')
            //将页面引导到第一页
            resetUserList()
        }).finally(() => {
        })
    })
}
//删除结束


//编辑抽屉组件开始
const formDrawerRef = ref(null)
const formRef = ref(null)
const form = reactive({})
const oldImageUrl = ref('')
const isSubmit = ref(false)

//表单验证规则
const rules = {
    username: [
        {
            required: true,
            message: '用户名不能为空',
            trigger: 'blur'
        },
    ],
    password: [
        {
            required: true,
            message: '密码不能为空',
            trigger: 'blur'
        },
    ],
    nickName: [
        {
            required: true,
            message: '昵称不能为空',
            trigger: 'blur'
        },
    ],
    mobile: [
        {
            required: true,
            validator: telValidator,
            trigger: 'blur'
        },
    ],
    email: [
        {
            required: true,
            validator: emailValidator,
            trigger: 'blur'
        },
    ],
}



//打开抽屉
const handleEdit = async function (item) {
    console.log(item)
    isAddOrEdit.value = false
    formDrawerRef.value.open()
    await nextTick(()=>{
        form.id = item.id
        form.imageUrl = item.imageUrl
        form.username = item.username
        form.nickName = item.nickName
        form.mobile = item.mobile
        form.email = item.email
        form.isAccountNonExpired = item.isAccountNonExpired
        form.isAccountNonLocked = item.isAccountNonLocked
        form.isCredentialsNonExpired = item.isCredentialsNonExpired
        form.isEnabled = item.isEnabled
        oldImageUrl.value = form.imageUrl
    }) 
}

//新增操作
const handleAdd = async function () {
    console.log(form)
    isAddOrEdit.value = true

    formDrawerRef.value.open()
    formDrawerRef.value.hideLoading()
    
    //重新进行初始化
    await nextTick(()=>{
        delete form.id
        form.isAccountNonExpired = 1,
        form.isAccountNonLocked = 1,
        form.isCredentialsNonExpired = 1,
        form.isEnabled = 1
    })
}
// 删除图片
const deleteImg = function (imageUrl) {
    // 进行编辑的操作
        // 发送请求删除数据库中的原本图片链接
        deletePic(imageUrl).then(res => {
            toast('删除图片成功')
        }).catch(err=>{
            console.log(err)
        })
}


//上传图片
const uploadMainImg = function (file) {
    //创建表单结构
    console.log(file)
    const data = new FormData()
    data.append('file', file.file)

    uploadPic(data).then(res => {
        // 回显图片
        form.imageUrl = res.data.data
        // 将之前的图片删除，
        if(oldImageUrl.value !== ''){
            deleteImg(oldImageUrl.value)
        }
        oldImageUrl.value = res.data.data
    }).catch(error => {
        console.log(error)
        toast('上传失败', "error")
    })
}


const drawerSubmit = async () => {
    formRef.value.validate(async (valid) => {
        const data = {...form}
        console.log('提交的数据为:')
        console.log(data)
        formDrawerRef.value.showLoading()
        if (!valid) {
            formDrawerRef.value.hideLoading()
            return false
        } else {
            console.log(isAddOrEdit.value)
            const fn = isAddOrEdit.value ? addUser(data) : updataUser(data)
            await fn
                .then(res => {
                    //后续可以加判断操作
                    console.log(res)
                    isSubmit.value = true
                    formDrawerRef.value.close()
                    //将页面引导到第一页
                    toast(drawerTitile.value + '成功')
                    resetUserList()
                })
                .catch((err)=>{
                    console.log(err)
                })
                .finally(() => {
                    isSubmit.value = false
                    formDrawerRef.value.hideLoading()
                })
        }
    })
}

const cleanForm = function(){
    if(form.imageUrl && !isSubmit.value && isAddOrEdit.value){
        deleteImg(form.imageUrl)
    }
    formRef.value.resetFields()
}

//编辑抽屉组件结束


//角色分配操作开始
const assignRef = ref(null)
const assignTitle = ref('修改角色')
const assignFormRef = ref(null)
const assignSearchForm = reactive({})
const assignTableRef = ref(null)
const assignTable = ref([])
const roleids = ref([])
const isRoleListLoading = ref(false)
const uid = ref('')

const rolePage = reactive({
    current: 1,
    size: 20,
    total: 0
})


const assignRole = async function (id) {

    assignRef.value.hideLoading()
    assignRef.value.open()
        //设置列表中进行分配角色的用户id
    await nextTick(()=>{
        uid.value = id
    })
    
    await InitRole(id)
}

//查询角色
const findRole = async function () {
    // //重新将表单至空
    // assignFormRef.value.resetFields()
    await InitRole()
}   

//重置操作
const resetRoleForm = async function(){
    assignFormRef.value.resetFields()
    await InitRole()
}

//初始化数据函数
const InitRole = async function (id) {

    const data = {...rolePage,...assignSearchForm}
    console.log('查询字段为')
    console.log(data)

    isRoleListLoading.value = true

    //查看所有的角色信息
    await searchRole(data).then(res => {
        assignTable.value = res.data.data.records
        console.log(res)
    })

    //根据用户id查询到该用户对应的所有角色id
    await getUserRoleId(uid.value).then(res => {
        roleids.value = res.data.data
        console.log(res)
    })

    //进行对比数据,然后改变checked
    await roleids.value.forEach(async (item1) => {
        assignTable.value.forEach(item2 => {
            if (item1 === item2.id) {
                item2.checked = true
            }
        })
    })
    isRoleListLoading.value = false
}

//分页
const roleHandleSizeChange = function(){
    InitRole()
}
const roleHandleCurrentChange = function(){
    InitRole()
}

//选中之后的操作
//反选
const select = function () {
    assignTable.value.forEach(t => {
        assignTableRef.value.toggleRowSelection(t, t.checked)
    })
}
//全选
const selectAll = function (row) {
    assignTable.value.forEach(t => {
        t.checked = !!row[0]
    })
}
//提交
const assignRolesSubmit = async function () {
    //这里将checked为true的值拿出来进行处理
    assignRef.value.showLoading()
    let targetArr = []
    assignTable.value.forEach(t => {
        if (t.checked) {
            targetArr.push(t.id)
        }
    })

    console.log('提交的数据为')
    console.log(targetArr)

    await updataUserRole(uid.value, targetArr).then(res => {
        console.log(res)
        toast('修改成功')
        assignRef.value.close()
        resetUserList()
    }).finally(() => {
        assignRef.value.hideLoading()
    })
}

const cleanRoleForm = function(){
    assignFormRef.value.resetFields()
}

//角色分配操作结束

//修改密码操作开始
const chgePwdRef = ref(null)
const chgePwdform = reactive({
    oldPassword: '',
    newPassword: ''
})
const chgePwdRules = {
    oldPassword: [
        {
            required: true,
            message: '旧密码不能为空',
            trigger: 'blur'
        },
    ],
    newPassword: [
        {
            required: true,
            message: '新密码不能为空',
            trigger: 'blur'
        },
    ],
}
const chgePwdFormRef = ref(null)
const chgePwdTitle = ref('修改密码')


const chgePwd = async function (id) {
    chgePwdRef.value.hideLoading()
    chgePwdRef.value.open()
    await nextTick(()=>{
        //将获取到的id再次赋值给uid
        uid.value = id
    })
}
const cleanPwdForm = function () {
    //将带有prop的表单进行清空
    chgePwdFormRef.value.resetFields()
}
const chgePwdSubmit = function () {
    const validData = {
            oldPassword: chgePwdform.oldPassword,
            userId: uid.value
    }
    console.log('提交的表单数据为:')
    console.log(chgePwdform)
    console.log('检验旧密码的对象为:')
    console.log(validData)

    chgePwdFormRef.value.validate(async (valid) => {
        chgePwdRef.value.showLoading()
        if (!valid) {
            chgePwdRef.value.hideLoading()
            return false
        }
        await validateOldPassword(validData).then(res=>{
            console.log(res)
        })
        await updataPassword(uid.value, chgePwdform)
            .then(res => {
                toast("修改密码成功")
                chgePwdRef.value.close()
                //分页至于第一页
                resetUserList()
            })
            .finally(() => {
                chgePwdRef.value.hideLoading()
            })
    })
}
//修改密码组件结束

//操作栏结束


//查找按钮 重置按钮 新增按钮数据开始
//查找操作
const findUser = async function () {
    page.current = 1
    Init()
}
//重置操作
const resetUserList = function(){
    searchRef.value.resetFields()
    page.current = 1
    Init()
}

//查找按钮 重置按钮 新增按钮数据结束






//使用watch进行监听事件开始(开发进行检测作用)
// watch(form, (newVal, oldVal) => {
//     console.log(newVal)
// }, { immediate: true });
//使用watch进行监听事件结束
</script>
<style scoped>
.form {
    @apply flex justify-start items-center
}

.btn{
    margin: 0 10px;
}

.image-slot {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    background: var(--el-fill-color-light);
    color: var(--el-text-color-secondary);
    font-size: 30px;
}

.avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
}

.avatar-uploader .el-upload:hover {
    border-color: #409EFF;
}

.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
}

.avatar {
    width: 178px;
    height: 178px;
    display: block;
}

.roleList-scrollbar {
    max-width: 800px;
    max-height: 160px;
}
</style>